<template>
	<view class="e-sliders" :style="slidersStyle" :id="elId" ref="eSlidersRef">
		<!-- weex中没有zIddex这个概念，故层级低的元素应当放在前面 -->
		<view class="e-sliders__content">
			<text class="e-sliders__content__text">{{ props.startText }}</text>
		</view>
		<view class="e-sliders__body" :style="bodyStyle" @touchstart="handleStart" @touchmove="handleMove"
			@touchend="handleEnd">
			<view class="e-sliders__hood">
				<text class="e-sliders__hood__text">{{ isEnd ? props.endText : '' }}</text>
			</view>
			<view :style="[blockStyle]" id="slider"  class="e-sliders__block">
				<slot />
			</view>
		</view>
	</view>
</template>
<script lang="ts">
	import {defineComponent} from 'vue'
	import mpMixin from '../../libs/mixin/mpMixin'
	/**
	 * sliders 滑块
	 * @description 该组件适用于需要滑动验证或滑动开启某项功能的场景
	 * @tutorial https://www.uviewui.com/components/overlay.html
	 * @property {String}	          startText		          未开始滑动时，滑块的文字
	 * @property {String}	          endText		          滑动完成后显示的文字
	 * @property {String}	          bgColor 	          	  组件背景颜色，默认#333333
	 * @property {String}	          activeBgColor    		  滑块拖动时，滑块按钮左侧区域的背景颜色，为空则使用blockBgColor
	 * @property {String | Number}	  height		          组件高度，默认50px
	 * @property {String}	          blockBgColor		      滑块按钮的背景颜色，默认#3c9cff
	 * @property {String}	          blockActiveBgColor      滑动完成后滑块按钮的背景颜色，默认#fff
	 * @property {String | Number}	  blockWidth		      滑块按钮的宽度，默认80px
	 * @property {String | Number}	  blockRound		      滑块按钮圆角值，默认4px
	 * @property {Boolean}	  		  autoReset 			  滑动完成后是否自动复位
	 * @property {String | Number}	  duration 			  	  滑动完成后多久自动复位,只在autoReset为true时生效
	 * @property {String | Number}	  round					  圆角值
	 * @property {Object}			  customStyle	          定义需要用到的外部样式
	 * @event {Function} change 滑块滑动事件
	 * @event {Function} end 滑动完成事件
	 * @example <e-sliders ></e-sliders>
	 */
	export default defineComponent({
		name: 'e-sliders',
		mixins: [mpMixin]
	})
</script>
<script lang="ts" setup>
	import {
		ref,
		computed,
		onMounted,
		toRefs,
		getCurrentInstance
	} from 'vue'
	import {
		useNamespace,
		useDefaultProps
	} from '../../libs/hooks'
	import {
		sleep,
		getRect,
		getNvueRect,
		nanoid
	} from '../../libs/utils'
	import {
		addUnit
	} from "../../libs/utils/_utils";
	import {
		slidersProps,
		slidersEmits
	} from './props'
	import type {
		StyleProperties
	} from "../../libs/tokens";
	import componentsProps, {
		type DefaultProps
	} from "../../libs/config/componentsProps";

	const {
		sliders: slidersDefaultProps
	} = toRefs(componentsProps);
	
	const ctx = getCurrentInstance()

	const _props = defineProps(slidersProps)

	const props = useDefaultProps < DefaultProps['sliders'] > (_props, slidersDefaultProps);
	const emit = defineEmits(slidersEmits)
	
	const elId = nanoid(21,true)

	const ns = useNamespace('sliders')

	const leftWidth = ref(0)
	//是否执行滑动函数
	const moveFlag = ref(false)
	//组件的宽度
	let reactWidth = 0
	//开始触摸距离屏幕左面的位置
	let startX = 0
	//是否允许滑动 判断是否滑动完成
	let finishFlag = false

	const isEnd = ref(false)


	const slidersStyle = computed(() => ({
		height: addUnit(props.value.height),
		backgroundColor: props.value.bgColor,
		borderRadius: addUnit(props.value.round)
	}))

	const durationStyle = computed(() => {
		if (moveFlag.value) {
			return '0ms'
		}
		return '800ms'
	})






	const bodyStyle = computed(() => {
		let style: StyleProperties = {
			width: addUnit(leftWidth.value + (props.value.blockWidth as number)),
			borderRadius: addUnit(props.value.round),
			backgroundColor: props.value.activeBgColor || props.value.blockBgColor,
			'transition-duration': durationStyle.value,
		}
		return style
	})

	const blockStyle = computed(() => {
		return {
			width: addUnit(props.value.blockWidth),
			height: addUnit(props.value.height),
			backgroundColor: isEnd.value ? props.value.blockActiveBgColor : props.value.blockBgColor,
			borderRadius: addUnit(props.value.blockRound)
		}
	})
	const handleStart = (e: any) => { //开始的触摸
		let {
			pageX
		} = e.changedTouches[0];
		startX = pageX; //记录按下时刻距离屏幕左侧的距离
		moveFlag.value = true;
	}
	const reset = () => { //重置滑动状态
		finishFlag = false
		moveFlag.value = false
		isEnd.value = false
		startX = 0
		leftWidth.value = 0

	}
	const finish = () => { //滑动完成状态
		finishFlag = true;

	}
	const handleMove = (e: any) => {
		if (!moveFlag.value) return;
		if (leftWidth.value >= (reactWidth - (props.value.blockWidth as number))) {
			// 滑动到最右侧
			if (!isEnd.value) {
				moveFlag.value = false;
				isEnd.value = true;
				emit("change", true)
				finish()
			}
		} else {
			let {
				pageX,
			} = e.changedTouches[0];
			let width = pageX - startX;
			//判断滑动边界是否超过左右两侧
			if (width >= (reactWidth - (props.value.blockWidth as number))) {
				width = reactWidth - (props.value.blockWidth as number)
			} else if (width <= 0) {
				width = 0
			}
			leftWidth.value = width;
			emit("change", false)
		}
	}
	// 滑动结束
	const handleEnd = () => {
		moveFlag.value = true;
		if (!finishFlag || leftWidth.value < (reactWidth - (props.value.blockWidth as number))) {
			//滑块没有滑动到最右侧，进行重置
			reset();
			emit("end", false)

		} else {
			emit("end", true)
			//设置了autoReset，则自动复位
			if (props.value.autoReset) {
				sleep(Number(props.value.duration)).then(() => {
					reset()
				})

			}
		}
	}
	const eSlidersRef = ref(null)
	onMounted(() => {
		// #ifdef APP-NVUE
		sleep(200).then(() => {
			getNvueRect(eSlidersRef.value).then(res => {
				// 获取组件宽度
				reactWidth = res?.width||0;
			})
		})

		// #endif
		// #ifndef APP-NVUE
		getRect(ctx,`#${elId}`).then(res => {
			// 获取组件宽度
			reactWidth = res.width!;
		})
		// #endif

	})
</script>

<style lang="scss" scoped>
	@import '../../libs/theme/sliders.scss';
</style>
